import re
import jwt
import hmac
import hashlib
import time
from functools import wraps
from datetime import datetime, timedelta
from flask import request, jsonify
from ..config import Config
from ..database import db_connection
import traceback

def validate_device_id(device_id):
    return True

def validate_timestamp(timestamp):
    try:
        return abs(time.time() - int(timestamp)) <= 300
    except:
        return False

def validate_user_id(user_id):
    """验证用户ID"""
    if isinstance(user_id, int):
        return 1 <= user_id <= 999999
    try:
        return 1 <= int(user_id) <= 999999
    except (ValueError, TypeError):
        return False

def device_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return jsonify(code=40101, message="Missing authorization header"), 401
        
        try:
            token_var = auth_header.split()[1]
            payload = jwt.decode(token_var, Config.SECRET_KEY, algorithms=["HS256"])
            kwargs['device_id'] = payload['sub']
        except jwt.ExpiredSignatureError:
            return jsonify(code=40102, message="Token expired"), 401
        except jwt.InvalidTokenError:
            return jsonify(code=40103, message="Invalid token"), 401
        except Exception as e:
            return jsonify(code=50001, message="Authentication failed"), 500
        
        return f(*args, **kwargs)
    return decorated

def admin_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        # 获取headers里的admin_id
        admin_id = request.headers.get('adminID')
        
        # 验证是否提供了admin_id
        if not admin_id:
            return jsonify(code=40101, message="缺少管理员ID"), 401
        
        try:
            # 使用header中的admin_id
            kwargs['admin_id'] = admin_id
            
            # 从数据库中查询管理员级别
            with db_connection() as conn:
                with conn.cursor() as cursor:
                    cursor.execute(
                        "SELECT admin_level FROM admin WHERE admin_id = %s AND is_active = 1",
                        (admin_id,)
                    )
                    admin = cursor.fetchone()
                    
            if not admin:
                return jsonify(code=40104, message="管理员不存在或已停用"), 401
                
            # 设置管理员级别
            kwargs['admin_level'] = admin['admin_level']
            
        except Exception as e:
            print(f"[ERROR] 管理员认证失败: {str(e)}")
            traceback.print_exc()
            return jsonify(code=50001, message="认证失败"), 500
        
        return f(*args, **kwargs)
    return decorated

def process_music_styles(device_id, date_str, styles):
    """
    注意：由于数据库中没有style表，此函数已被修改为仅记录日志而不执行实际操作。
    如果需要处理风格，请先在数据库中创建相应的表。
    """
    print(f"[WARNING] process_music_styles called but style table doesn't exist. Device: {device_id}, Date: {date_str}")
    print(f"[WARNING] Styles data that would have been processed: {styles}")
    
    # 返回空字典表示没有处理任何风格
    return {}

def get_device_secret(device_id):
    with db_connection() as conn:
        with conn.cursor() as cursor:
            cursor.execute(
                "SELECT device_key FROM device WHERE device_id = %s",
                (device_id,)
            )
            result = cursor.fetchone()
            return result['device_key'] if result else None

def get_current_datetime():
    """返回当前的日期时间，格式化为字符串"""
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

def generate_token(payload, expiration=24):
    """
    生成JWT令牌
    :param payload: 包含需要编码的数据的字典
    :param expiration: 过期时间（小时）
    :return: 生成的令牌
    """
    exp = datetime.utcnow() + timedelta(hours=expiration)
    payload.update({"exp": exp})
    return jwt.encode(payload, Config.SECRET_KEY, algorithm="HS256")

def verify_token(token):
    """
    验证JWT令牌
    :param token: 要验证的令牌
    :return: 解码后的数据或None（如果验证失败）
    """
    try:
        return jwt.decode(token, Config.SECRET_KEY, algorithms=["HS256"])
    except:
        return None